﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data;
using System.Data.Common;

using Ice.Toolkit.Data.Entity;
using Ice.Toolkit.Data.Sql;
using Ice.Toolkit.Data.ILInvoker;

namespace Ice.Toolkit.Data
{
    public class DataContext : DbHelper, IDataContext
    {
        protected DbTransaction Transaction { get; set; }

        public DataContext(string connectionString) : base(connectionString) { }
        public DataContext(string connectionString, string providerName) : base(connectionString, providerName) { }

        public int Insert<Entity>(Entity entity) where Entity : EntityBase<Entity>, new()
        {
            var insert = new InsertBuilder<Entity>(entity, this);
           
            insert.Build();

            return ExecuteSql(insert.SQLText, insert.DbParameters);
        }

        public int Update<Entity>(Entity entity) where Entity : EntityBase<Entity>, new()
        {
            var update = new UpdateBuilder<Entity>(entity, this);

            update.Build();

            return ExecuteSql(update.SQLText, update.DbParameters);
        }

        public int Delete<Entity>(Entity entity) where Entity : EntityBase<Entity>, new()
        {
            var delete = new DeleteBuilder<Entity>(this, entity);

            delete.Build();

            return ExecuteSql(delete.SQLText, delete.DbParameters);
        }

        public int Delete<Entity>(Expression<Func<Entity, Boolean>> whereExpression) where Entity : EntityBase<Entity>, new()
        {
            var delete = new DeleteBuilder<Entity>(this, whereExpression);

            delete.Build();

            return ExecuteSql(delete.SQLText, delete.DbParameters);
        }

        public IQuery<TEntity> Query<TEntity>(Expression<Func<TEntity, Boolean>> expression) where TEntity : EntityBase<TEntity>, new()
        {
            return (new Query<TEntity>(this)).Where(expression);
        }

        public IQuery<TEntity> Query<TEntity>() where TEntity : EntityBase<TEntity>, new()
        {
            return new Query<TEntity>(this);
        }

        public List<TEntity> Query<TEntity>(string sqlText, params DbParameter[] cmdParams) where TEntity : EntityBase<TEntity>, new()
        {
            if (Transaction == null)
            {
                using (IDataReader dataRead = ExecuteReader(sqlText, cmdParams))
                {
                    return new EntityBuilder<TEntity>(dataRead).CreateInstances();
                }
            }
            else
            {
                using (IDataReader dataRead = ExecuteReader(sqlText, Transaction, cmdParams))
                {
                    return new EntityBuilder<TEntity>(dataRead).CreateInstances();
                }
            }
        }

        public TEntity Single<TEntity>(string sqlText, params DbParameter[] cmdParams) where TEntity : EntityBase<TEntity>, new()
        {
            return Query<TEntity>(sqlText, cmdParams).FirstOrDefault();
        }

        public void TranBegin()
        {
            Transaction = CreateTransaction();
        }

        public void TranCommit()
        {
            if (Transaction != null)
            {
                try
                {
                    Transaction.Commit();
                }
                catch
                {
                    Transaction.Rollback();
                }
                finally
                {
                    Transaction.Dispose();
                }
            }
        }

        public int ExecuteSql(string sqlText, params DbParameter[] parameters)
        {
            return Transaction == null ? 
                ExecuteNonQuery(sqlText, parameters) : 
                ExecuteNonQuery(sqlText, Transaction, parameters);
        }
    }
}
